#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/12/4 13:34
# @Author : 闫峰
# @File    : listing_filter_9058.py
from decimal import Decimal
from utils.logging_tool.init_logger import init_logger
from utils.logging_tool.log_decorator import log_print_decorator
from utils.mongodb_control.batch_by_mongodb import MongoDBByBatch
from utils.otherutils.catch_exceptions import exception_handler_decorator
from utils.times_tool.time_control import count_time_decorator
import requests
from apps.zhcxkj_center_product.test.views.get_sku_goor_num_by_set import Inventory
from apps.zhcxkj_center_product.test.utils.rb_product_no_sale import RbProductNoSale
from common.setting import ensure_path_sep
from utils.mysqlUtils.db_pool import Database
from utils.mysqlUtils.mongodb_utils import MongoDBLink
from utils.otherutils.functions_control import get_date_by_days

# TODO 定义装饰器开关
switch = False
count_time_decorator_switch = True


class ListingFilterModel:
    """
    allegro listing 分级策略
    涉及表
    zhcxkj_center_strategy_comprehensive_db
    zhcxkj_center_order_db
    zhcxkj_center_promotion_db
    zhcxkj_center_listing_comprehensive_db

    涉及集合

    涉及接口
    https://api-dw.zhcxkj.com/dw/erp/salesvolume/platform/salessku

    """
    zhcxkj_center_strategy_comprehensive_db = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"),
                                                       "test_jdw_database")
    zhcxkj_center_order_db = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"), "test_jdw_database")
    zhcxkj_center_promotion_db = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"), "test_jdw_database")
    zhcxkj_center_listing_comprehensive_db = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"),
                                                      "test_jdw_database")
    env = "test_"

    def __init__(self, listing_template_id):

        t_allegro_listing_template_detail = f"t_allegro_listing_template_detail_{listing_template_id}"
        self.t_allegro_listing_template_detail = MongoDBLink(
            uri='mongodb://admin:Zhcx?2021@10.158.158.29:27017/?authSource=admin',
            dbname='zhcxkj_comprehensive_allegro', coll_name=t_allegro_listing_template_detail)
        self.listing_template_id = listing_template_id
        # 查询策略条件
        # todo  这里有一个坑
        get_strategy_conditions = f"""
        SELECT  
        a.`status`, -- 模板状态  1
        GROUP_CONCAT(b.category_id), -- 分类id 2
        a.listing_publish_start_time, -- listing上架开始时间 3
        a.listing_publish_end_time, -- listing上架结束时间 4
        a.price_min, -- 平台价格最小值 5 
        a.price_max, -- 平台价格最大值 6 
        a.listing_sale_min, -- listing销量最小值 7 
        a.listing_sale_max, -- listing销量最大值 8
        a.listing_sale_recent_days, -- listing最近几天的销量数据 9
        a.sku_sale_min, -- sku销量最小值 10
        a.sku_sale_max, -- sku销量最大值 11 
        a.sku_sale_recent_days, -- sku最近几天的销量数据，最大值90天 12
        a.in_promotion,  -- 促销状态，0：未参与促销折扣，1：已参与促销折扣 13
        a.listing_discount_min,  -- lisitng促销折扣最小值 14
        a.listing_discount_max,  -- lisitng促销折扣最大值 15
        a.listing_discount_type,  -- listing折扣值类型，0：同品折扣，1：不同品折扣集合 -1 全部 16
        a.has_published, -- '是否已上架，0：已上架，1：激活中 2:草稿 3:已下架', 17
        a.template_type, -- 0：创建促销，1：更改已参与促销折扣，删除促销活动 2:下架 3：调价', 18
        a.available_stock_min, -- 19
        a.available_stock_max, -- 20
        a.sku_listing_number, -- 21
        a.sku_active_number, -- 22
        a.filter_active_sku, -- 23
        a.source_sku_sale_min, -- 24
        a.source_sku_sale_max, -- 25
        a.source_sku_sale_recent_days, -- 26
        a.no_sale -- 27
        FROM {self.env}zhcxkj_center_strategy_comprehensive.t_allegro_listing_filter_template a
        LEFT JOIN {self.env}zhcxkj_center_strategy_comprehensive.t_allegro_listing_filter_category b ON a.id=b.listing_template_id
        WHERE a.id= %s
        and a.status =1
        """
        strategy_conditions = self.zhcxkj_center_strategy_comprehensive_db.fetch_all_tuple(get_strategy_conditions,
                                                                                           (self.listing_template_id,))

        if not len(strategy_conditions):
            raise Exception("未查询到过滤模版")
        # self.strategy_conditions = strategy_conditions
        self.category_id_list = strategy_conditions[0][1]
        if not self.category_id_list:
            self.category_id_list = []
        else:
            self.category_id_list = self.category_id_list.split(",")  # 分类idlist

        self.listing_publish_start_time = strategy_conditions[0][2]  # listing上架开始时间
        self.listing_publish_end_time = strategy_conditions[0][3]  # listing上架结束时间
        self.price_min = strategy_conditions[0][4]  # 平台价格最小值
        self.price_max = strategy_conditions[0][5]  # 平台价格最大值
        self.listing_sale_min = strategy_conditions[0][6]  # listing销量最小值
        self.listing_sale_max = strategy_conditions[0][7]  # listing销量最大值
        self.listing_sale_recent_days = strategy_conditions[0][8]  # listing最近几天的销量数据
        self.sku_sale_min = strategy_conditions[0][9]  # sku销量最小值
        self.sku_sale_max = strategy_conditions[0][10]  # sku销量最大值
        self.sku_sale_recent_days = strategy_conditions[0][11]  # sku最近几天的销量数据
        self.in_promotion = strategy_conditions[0][12]  # 促销状态，0：未参与促销折扣，1：已参与促销折扣 2 全部
        self.listing_discount_min = strategy_conditions[0][13]  # lisitng促销折扣最小值
        self.listing_discount_max = strategy_conditions[0][14]  # lisitng促销折扣最大值
        self.listing_discount_type = strategy_conditions[0][15]  # listing折扣值类型，0：同品折扣，1：不同品折扣集合
        self.has_published = strategy_conditions[0][16]  # 是否已上架，0：已上架，1：激活中 2:草稿 3:已下架' -1 全部
        self.template_type = strategy_conditions[0][17]  # 创建促销，1：更改已参与促销折扣，删除促销活动 2:下架 3：调价',4 自动刊登
        self.available_stock_min = strategy_conditions[0][18]  # 可用库存最小值
        self.available_stock_max = strategy_conditions[0][19]  # 可用库存最大值
        self.sku_listing_number = strategy_conditions[0][20]  # sku上架次数
        self.sku_active_number = strategy_conditions[0][21]  # sku在线listing数
        self.filter_active_sku = strategy_conditions[0][22]  # '是否过滤渠道在线sku,1:过滤，0：不过滤',
        self.source_sku_sale_min = strategy_conditions[0][23]  # 渠道sku销量最小值
        self.source_sku_sale_max = strategy_conditions[0][24]  # 渠道sku销量最大值
        self.source_sku_sale_recent_days = strategy_conditions[0][25]  # '渠道sku最近几天的销量数据，最大值90天,0:全部销量',
        self.no_sale = strategy_conditions[0][26]  # '0:不屏蔽禁售，1：屏蔽禁售',
        if self.no_sale:
            self.nosales_sku_list = RbProductNoSale.get_no_sale_sku_list(67, None)

    @count_time_decorator(switch=count_time_decorator_switch)
    @exception_handler_decorator
    def sku_filter(self, source_id):
        INFO, ERROR, WARNING = init_logger()
        num = source_id % 8 + 1
        get_listing_list = None
        # 解析listing 状态
        if self.has_published == "-1":
            get_listing_list = f"""
            SELECT id,category_id,market_create_time,price,sku,offer_id,source_sku
            FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
            WHERE id >%s
            and source_id=%s
            and is_deleted=0
            # and offer_id = 13853392898
            order by id
            limit 1000
            """
        elif self.has_published == "0":
            # 分批次拉取数据源 在线的listing数据
            get_listing_list = f"""
            SELECT 
            id,
            category_id,
            price,
            quantity,
            watchers_count,
            watchers_conversion_rate,
            visits_count,
            day_thirty_sales,
            day_sixty_sales,
            day_ninety_sales,
            total_sales,
            thirty_sales_conversion_rate,
            sku,
            source_sku
            FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
            WHERE id >%s
            and source_id=%s
            and is_deleted=0
            and status = 3
            order by id
            limit 1000
            """
        id_index = 0
        offer_id_total = set()
        count_num = 0
        while True:
            data_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_listing_list, (id_index, source_id))
            if not len(data_list):
                # 查询不到数据 退出循环
                break
            id_index = data_list[-1][0]
            data_set = set(data_list)
            count_num += len(data_set)
            WARNING.logger.warning(f"遍历{count_num}个\toffer_id_total总数 {len(offer_id_total)}个")
            WARNING.logger.warning(f"index={id_index}")
            if not data_set:
                continue
            # 平台分类 多选
            if self.category_id_list:
                data_set = self.filter_category(data_set=data_set)
            if not data_set:
                continue
            # 上架时间 区间
            if self.listing_publish_start_time:
                data_set = self.filter_publist_time(data_set=data_set)
            if not data_set:
                continue
            # 价格 区间
            if any([self.price_min is not None, self.price_max is not None]):
                data_set = self.filter_price(data_set=data_set)
            if not data_set:
                continue
            # 是否参与促销 '促销状态，0：未参与促销折扣，1：已参与促销折扣 2全部',  单选
            if self.in_promotion in [0, 1]:
                self.filter_is_participate_promotion(data_set=data_list)
            # # listing促销折扣值 区间
            if any([self.listing_discount_min is not None, self.listing_discount_max is not None]):
                data_set = self.filter_promotion(data_set=data_set, num=num)
            if not data_set:
                continue
            # sku上架次数 刊登业务专属  单输入框
            if self.sku_listing_number:
                data_set = self.filter_sku_listing_number(data_set=data_set, num=num, source_id=source_id)
            if not data_set:
                continue
            # 过滤渠道在线sku 刊登业务专属  单选
            if self.filter_active_sku:
                data_set = self.filter_filter_active_sku(data_set=data_set, num=num, source_id=source_id)
            if not data_set:
                continue
            # sku在线listing数 刊登业务专属  单输入框
            if self.sku_active_number:
                data_set = self.filter_listing_online_num(data_set=data_set)
            if not data_set:
                continue
            # 所有平台SKU销量 区间
            # todo 这里在解析条件时，需要合理的判断入口
            if any([self.sku_sale_min, self.sku_sale_max]):
                data_set = self.filter_sku_sales(data_set=data_set)
            if not data_set:
                continue
            # 平台SKU销量 区间
            if any([self.listing_sale_min, self.listing_sale_max]):
                data_set = self.filter_platform_sku_sales(data_set=data_set)
            if not data_set:
                continue
            # 平台渠道SKU销量   区间
            # TODO 这里演示下这个条件基本会将数据筛没 在调试时 可以暂时不勾选这个
            if any([self.source_sku_sale_min, self.source_sku_sale_max]):
                data_set = self.filter_source_sku_sale(data_set=data_set, source_id=source_id)
            if not data_set:
                continue
            # 禁售sku过滤 刊登业务专属 单选
            if self.no_sale == 1:
                data_set = self.filter_no_sale(data_set=data_set)
            if not data_set:
                continue
            # 可用库存过滤 区间
            if any([self.available_stock_min, self.available_stock_max]):
                data_set = self.filter_good_num(data_set=data_set)
            if not data_set:
                continue
            offer_id_total |= set(map(lambda x: x[5], data_set))

        if not offer_id_total:
            ERROR.logger.error(f"最终过滤结果数为0")
            return
        INFO.logger.info(f"最终过滤结果数为{len(offer_id_total)}")
        actual_offer_id_set = self.get_actual_offer_id_set(self.listing_template_id, source_id)
        if offer_id_total != actual_offer_id_set:
            ERROR.logger.error(f"分级策略={self.listing_template_id} source_id= {source_id} 执行不准确")
        else:
            INFO.logger.info(f"分级策略={self.listing_template_id} source_id= {source_id} 验证无问题")


    @log_print_decorator(switch=switch, filter_mame="是否参与促销")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_is_participate_promotion(self, data_set):
        offer_id_set = set(map(lambda x: x[5], data_set))
        data_result_set = None
        get_exist_offer_participate_list = f"""
        SELECT offer_id
        FROM {self.env}zhcxkj_center_promotion.t_allegro_promotion_detail 
        WHERE 
         offer_id in %s
        """
        exist_offer_participate_list = self.zhcxkj_center_promotion_db.fetch_all_tuple(get_exist_offer_participate_list,
                                                                                       (offer_id_set,))
        exist_offer_list = []
        if not len(exist_offer_participate_list):
            exist_offer_list = []
        else:
            exist_offer_list = list(map(lambda x: x[0], exist_offer_participate_list))
        if self.in_promotion == 0:
            data_result_set = set(filter(lambda x: x[5] not in exist_offer_list, data_set))
        elif self.in_promotion == 1:
            data_result_set = set(filter(lambda x: x[5] in exist_offer_list, data_set))
        return data_result_set

    @log_print_decorator(switch=switch, filter_mame="listing促销折扣值")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_promotion(self, data_set, num):
        # 判断促销折扣值 是否勾选 如果勾选  判断listing_discount_type = -1 （全部）0：同品折扣，1：不同品折扣集合
        """
        # 判断促销折扣值 是否勾选 如果勾选  判断listing_discount_type = -1 （全部）0：同品折扣，1：不同品折扣集合
        如果时全部 筛选出参加活动的offer  percentage 符合策略
        如果是 1 筛选出的参加 不同品折扣集合活动 的offer  percentage 符合策略  同品折扣 不用过滤
        如果是 0 筛选出的参加 同品折扣活动 的offer  percentage 符合策略  不同品折扣集合 不用过滤
        """
        if self.listing_discount_type == -1:
            data_set = self.filter_promotion_discount_value_all(data_set, num)
        else:
            data_set = self.filter_promotion_discount_value_by_promotion_type(data_set, num,
                                                                              self.listing_discount_type)
        return data_set

    @log_print_decorator(switch=switch, filter_mame="渠道在线SKU")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_filter_active_sku(self, data_set, num, source_id):
        """
        过滤渠道在线SKU
        :param data_set:  上一次的数据集
        :param num: 分片键
        :param source_id: 渠道id
        :return:
        """
        origin_data_set = data_set
        sku_set = set(map(lambda x: x[4], data_set))
        get_num = f"""
        SELECT sku 
        `FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
        WHERE source_id=%s
        AND sku in %s
        and status =3
                """
        sku_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_num, (source_id, sku_set))
        sku_list_map = list(map(lambda x: x[0], sku_list))
        sku_list_map = list(set(sku_list_map))
        data_set = set(filter(lambda x: x[4] not in sku_list_map, origin_data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="sku上架次数")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_sku_listing_number(self, data_set, num, source_id):
        """
        sku上架次数
        :param data_set: 上一次数据集
        :param num: 分片键
        :param source_id: 渠道id
        :return:
        """
        origin_data_set = data_set
        sku_set = set(map(lambda x: x[4], data_set))
        # TODO 这里一起研究下所有的问题
        get_num = f"""
        SELECT sku 
        FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
        WHERE source_id=%s
        AND sku in %s
        GROUP BY source_id,sku
        having count(*) > %s
            
        """
        sku_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_num, (
            source_id, sku_set, self.sku_listing_number))
        sku_list_map = list(map(lambda x: x[0], sku_list))
        data_set = set(filter(lambda x: x[4] not in sku_list_map, origin_data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="sku上架次数")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_listing_online_num(self, data_set):
        """
        sku上架次数
        :param data_set:  上一次数据集
        :return:
        """
        origin_data_set = data_set
        sku_set = set(map(lambda x: x[4], data_set))
        list_num = [1, 2, 3, 4, 5, 6, 7, 8]
        sku_num = {}
        batch_list = ListingFilterModel.batch_list(sku_set, 20)
        # TODO 这里一起研究下所有的问题
        for batch in batch_list:
            for num in list_num:

                sql = f"""
                SELECT sku,count(1) num 
                FROM  `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}`
                WHERE sku in %s
                AND status=3
                AND is_deleted=0
                GROUP BY sku
                """
                sku_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(sql, (set(batch),))
                if not len(sku_list):
                    continue
                for sku, num_ in sku_list:
                    if sku not in sku_num:
                        sku_num[sku] = num_
                    else:
                        sku_num[sku] += num_

        # 得到        sku_num
        matching_sku_list = [sku for sku, num in sku_num.items() if num <= self.sku_active_number]
        data_set = set(filter(lambda x: x[4] in matching_sku_list, origin_data_set))
        return data_set

    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_promotion_discount_value_all(self, data_set, num):
        """
        过滤 促销折扣
        :param data_set: 上一次数据集
        :param num: 分片键
        :return:
        """
        # data_set 转化为 offer_id_set 集合
        origin_offer_id_set = set(map(lambda x: x[5], data_set))
        sql = f"""
        SELECT b.offer_id,a.percentage,a.promotion_type
        FROM {self.env}zhcxkj_center_promotion.t_allegro_promotion a
        LEFT JOIN  {self.env}zhcxkj_center_promotion.t_allegro_promotion_detail b ON a.promotion_id=b.promotion_id
        WHERE b.offer_id in %s
        """
        res = self.zhcxkj_center_promotion_db.fetch_all_tuple(sql, (origin_offer_id_set,))
        # 过滤掉不符合的数据
        percentage_min = self.listing_discount_min
        percentage_max = self.listing_discount_max
        if percentage_min:
            percentage_min = Decimal(str(percentage_min))
        if percentage_max:
            percentage_max = Decimal(str(percentage_max))
        if all([percentage_min, percentage_max]):
            # self.listing_discount_min 由 int类型转化为 decimal类型
            res = set(filter(lambda x: percentage_min <= x[1] <= percentage_max, res))
        elif all([not percentage_min, percentage_max]):
            res = set(filter(lambda x: x[1] <= percentage_max, res))
        if all([percentage_min, not percentage_max]):
            res = set(filter(lambda x: percentage_min <= x[1], res))
        # 转化成offer_id_set
        after_filter_offer_id_set = set(map(lambda x: x[0], res))
        if not after_filter_offer_id_set:
            return set()
        # 还原
        get_data_set = f"""
                SELECT id,category_id,market_create_time,price,sku,offer_id
        FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
        WHERE offer_id in %s
        """
        listing_id_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_data_set,
                                                                                      (after_filter_offer_id_set,))
        return set(listing_id_list)

    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_promotion_discount_value_by_promotion_type(self, data_set, num, promotion_type):
        """
        按照促销类型过滤
        :param data_set: 上一次数据集
        :param num: 分片键
        :param promotion_type: 促销类型
        :return:
        """
        # data_set 转化为 offer_id_set 集合
        origin_offer_id_set = set(map(lambda x: x[5], data_set))
        filter_offer_id_set = set()
        # 查询出不符合的同品listing
        if all([self.listing_discount_min, self.listing_discount_max]):
            sql1 = f"""
            SELECT b.offer_id
            FROM {self.env}zhcxkj_center_promotion.t_allegro_promotion a
            LEFT JOIN  {self.env}zhcxkj_center_promotion.t_allegro_promotion_detail b ON a.promotion_id=b.promotion_id
            WHERE b.offer_id in %s
            and a.percentage >= %s
            and a.percentage <= %s
            and a.promotion_type= %s
            """
            res1 = self.zhcxkj_center_promotion_db.fetch_all_tuple(sql1, (
                origin_offer_id_set, self.listing_discount_min, self.listing_discount_max, promotion_type))
            filter_offer_id_set = set(map(lambda x: x[0], res1))
            # after_filter_offer_id_set = origin_offer_id_set - filter_offer_id_set
        elif all([not self.listing_discount_min, self.listing_discount_max]):

            sql2 = f"""
            SELECT b.offer_id
            FROM {self.env}zhcxkj_center_promotion.t_allegro_promotion a
            LEFT JOIN  {self.env}zhcxkj_center_promotion.t_allegro_promotion_detail b ON a.promotion_id=b.promotion_id
            WHERE b.offer_id in %s
            and a.percentage <= %s
            and a.promotion_type = %s
            """
            res2 = self.zhcxkj_center_promotion_db.fetch_all_tuple(sql2, (
                origin_offer_id_set, self.listing_discount_max, promotion_type))
            filter_offer_id_set = set(map(lambda x: x[0], res2))
            # after_filter_offer_id_set = origin_offer_id_set - filter_offer_id_set

        elif all([self.listing_discount_min, not self.listing_discount_max]):

            sql2 = f"""
            SELECT b.offer_id
            FROM {self.env}zhcxkj_center_promotion.t_allegro_promotion a
            LEFT JOIN  {self.env}zhcxkj_center_promotion.t_allegro_promotion_detail b ON a.promotion_id=b.promotion_id
            WHERE b.offer_id in %s
            and a.percentage >= %s
            and a.promotion_type = %s
            """
            res2 = self.zhcxkj_center_promotion_db.fetch_all_tuple(sql2, (
                origin_offer_id_set, self.listing_discount_min, promotion_type))
            filter_offer_id_set = set(map(lambda x: x[0], res2))
            # after_filter_offer_id_set = origin_offer_id_set - filter_offer_id_set
        if not filter_offer_id_set:
            return filter_offer_id_set
        # 还原
        get_data_set = f"""
                SELECT id,category_id,market_create_time,price,sku,offer_id
        FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
        WHERE offer_id in %s
        """
        listing_id_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_data_set,
                                                                                      (filter_offer_id_set,))
        return set(listing_id_list)

    @log_print_decorator(switch=switch, filter_mame="平台分类")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_category(self, data_set):
        """
        平台分类条件过滤
        :param data_set: 上一次数据集
        :return:
        """
        data_set = set(filter(lambda x: str(x[1]) in self.category_id_list, data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="禁售SKU")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_no_sale(self, data_set):
        """
        禁售SKU过滤
        :param data_set:
        :return:
        """
        data_set = set(filter(lambda x: x[4] not in self.nosales_sku_list, data_set))
        return data_set

    # @count_time
    @log_print_decorator(switch=switch, filter_mame="上架时间")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_publist_time(self, data_set):
        """
        刊登时间条件过滤
        :param data_set: 上一次数据集
        :return:
        """
        # origin_data_set = data_set
        data_set = set(
            filter(lambda x: self.listing_publish_start_time <= x[2] <= self.listing_publish_end_time, data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="价格")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_price(self, data_set):
        """
        价格条件过滤
        :param data_set: 上一次数据集
        :return:
        """
        if self.price_min:
            if self.price_max:
                data_set = set(filter(lambda x: self.price_min <= x[3] <= self.price_max, data_set))
            else:
                data_set = set(filter(lambda x: self.price_min <= x[3], data_set))
        elif self.price_min == Decimal("0"):
            if self.price_max is None:
                data_set = set(filter(lambda x: self.price_min <= x[3], data_set))
            elif self.price_max is not None:
                data_set = set(filter(lambda x: x[3] <= self.price_max, data_set))
        elif self.price_min is None:
            data_set = set(filter(lambda x: x[3] <= self.price_max, data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="可用库存")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_good_num(self, data_set):
        """
        可用库存过滤
        :param data_set: 上一次数据集
        :return:
        """
        # 优化
        sku_set = set(map(lambda x: x[4], data_set))
        sku_good_num_dict = Inventory(sku_set,{5312, 333}).get_set()
        if all([self.available_stock_min, self.available_stock_max]):
            data_set = set(filter(lambda x: self.available_stock_min <= sku_good_num_dict.get(x[4],0) <= self.available_stock_max,
                                  data_set))

        elif all([not self.available_stock_min, self.available_stock_max]):
            data_set = set(
                filter(lambda x: sku_good_num_dict.get(x[4],0) <= self.available_stock_max,
                       data_set))

        elif all([self.available_stock_min, not self.available_stock_max]):
            data_set = set(
                filter(lambda x: self.available_stock_min <= sku_good_num_dict.get(x[4],0),
                       data_set))
        return data_set
    @staticmethod
    def batch_list(input_list, batch_size):
        """
        将一个列表分成指定大小的多个批次。

        :param input_list: 要分批的原始列表。
        :param batch_size: 每个批次的元素数量。
        :return: 分批后的列表，每个批次是一个子列表。
        """
        input_list = list(input_list)
        batches = []
        for i in range(0, len(input_list), batch_size):
            batch = input_list[i:i + batch_size]
            batches.append(batch)
        return batches

    @log_print_decorator(switch=switch, filter_mame="平台渠道SKU销量")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_source_sku_sale(self, data_set, source_id):
        """
        平台渠道SKU销量过滤
        rb_report_order_source_sku_day
        rb_report_order_source_sku_year
        :param data_set:
        :return:
        """
        to_source_sku_set = set(map(lambda x: x[6], data_set))
        source_sku_sales_dict_ = {}
        if self.source_sku_sale_recent_days == 0:
            # 总销量
            get_sales = f"""
            SELECT order_source_id,order_source_sku, SUM(sales_num) sales
            FROM {self.env}zhcxkj_center_order.rb_report_order_source_sku_year
            WHERE order_source_id=%s
            AND order_source_sku in %s
            GROUP BY order_source_id,order_source_sku
            """
            model_sales = self.zhcxkj_center_order_db.fetch_all_tuple(get_sales, (source_id, to_source_sku_set))
            # 这里要注意逻辑 查询不到的销量=0
            if len(model_sales):
                source_sku_sales_dict_ = {order_source_sku: sales for order_source_id, order_source_sku, sales in
                                          model_sales}

        else:
            date_days = get_date_by_days(self.source_sku_sale_recent_days).strftime('%Y-%m-%d')
            get_sales = f"""
            SELECT order_source_sku, SUM(sales_num) sales
            FROM {self.env}zhcxkj_center_order.rb_report_order_source_sku_day
            WHERE 
             order_source_sku in %s
            and sales_day  >= %s
            and order_source_id=%s
            GROUP BY order_source_id,order_source_sku
            """
            model_sales = self.zhcxkj_center_order_db.fetch_all_tuple(get_sales,
                                                                      (to_source_sku_set, date_days, source_id))
            if len(model_sales):
                source_sku_sales_dict_ = {order_source_sku: sales for order_source_sku, sales in model_sales}

        if all([self.source_sku_sale_min, self.source_sku_sale_max]):
            data_set = set(filter(
                lambda x: self.source_sku_sale_min <= source_sku_sales_dict_.get(x[6], 0) <= self.source_sku_sale_max,
                data_set))
        elif all([not self.source_sku_sale_min, self.source_sku_sale_max]):
            data_set = set(filter(
                lambda x: source_sku_sales_dict_.get(x[6], 0) <= self.source_sku_sale_max,
                data_set))
        elif all([self.source_sku_sale_min, not self.source_sku_sale_max]):
            data_set = set(filter(
                lambda x: self.source_sku_sale_min <= source_sku_sales_dict_.get(x[6], 0),
                data_set))
        return data_set

    def cover_to_listing(self, num, offer_id_set):
        get_data_set = f"""
        SELECT id,category_id,market_create_time,price,sku,offer_id,source_sku
        FROM `{self.env}zhcxkj_center_listing_comprehensive`.`t_allegro_listing_{num}` 
        WHERE offer_id in %s
        """
        data_list = self.zhcxkj_center_listing_comprehensive_db.fetch_all_tuple(get_data_set,
                                                                                (offer_id_set,))
        return set(data_list)

    def get_actual_offer_id_set(self, listing_template_id, source_id):
        """
        得到实际执行数据集合
        :param listing_template_id: 分级策略id
        :param source_id: 渠道id
        :return:
        """
        actual_offer_id_set = set()
        MongoDBByBatchExe = MongoDBByBatch(self.t_allegro_listing_template_detail)
        filters_ObjectId = {
            "$and": [
                {"listingTemplateId": listing_template_id},
                {"sourceId": source_id}
            ]
        }
        projection1 = {"offerId": 1, "_id": 1}
        generator = MongoDBByBatchExe.get_data(filters_ObjectId,projection1,1000)
        while True:
            actual_offer_id_list = next(generator)
            if not len(actual_offer_id_list):
                break
            actual_offer_id_set |= set(map(lambda x: x['offerId'], actual_offer_id_list))
        return actual_offer_id_set

    @log_print_decorator(switch=switch, filter_mame="所有平台SKU销量")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_sku_sales(self, data_set):

        """
        SKU销量过滤
        :param data_set: 上一次数据集
        :return:
        """
        oringin_data_set = data_set
        sku_list = list(map(lambda x: x[4], data_set))
        #   根据策略规则获取销量
        if not self.sku_sale_recent_days:
            sku_sale_recent_days = None
        else:
            sku_sale_recent_days = self.sku_sale_recent_days

        # 得到sku 销量字典
        sales_dict = self.get_platform_sales(sku_list, "all", sku_sale_recent_days)
        # 匹配策略
        if all([self.sku_sale_min, not self.sku_sale_max]):
            sales_dict = set(filter(lambda x: self.sku_sale_min <= x[1], sales_dict.items()))

        elif all([not self.sku_sale_min, self.sku_sale_max]):
            sales_dict = set(filter(lambda x: x[1] <= self.sku_sale_max, sales_dict.items()))

        elif all([self.sku_sale_min, self.sku_sale_max]):
            sales_dict = set(filter(lambda x: self.sku_sale_min <= x[1] <= self.sku_sale_max,
                                    sales_dict.items()))

        # 得到符合策略的sku列表
        sku_list = list(map(lambda x: x[0], sales_dict))
        # 得到过滤后的集合
        data_set = set(filter(lambda x: x[4] in sku_list, oringin_data_set))
        return data_set

    @log_print_decorator(switch=switch, filter_mame="平台SKU销量")
    @count_time_decorator(switch=count_time_decorator_switch)
    def filter_platform_sku_sales(self, data_set):
        """
        平台listing销量过滤
        :param data_set: 上一次数据集
        :return:
        """
        oringin_data_set = data_set
        sku_list = list(map(lambda x: x[4], data_set))
        #   根据策略规则获取销量
        if not self.listing_sale_recent_days:
            sku_sale_recent_days = None
        else:
            sku_sale_recent_days = self.listing_sale_recent_days
        # 得到sku 销量字典
        sales_dict = self.get_platform_sales(sku_list, 67, sku_sale_recent_days)
        # 匹配策略
        if all([self.listing_sale_min, self.listing_sale_max]):
            sales_dict = set(filter(lambda x: self.listing_sale_min <= x[1] <= self.listing_sale_max,
                                    sales_dict.items()))

        elif all([not self.listing_sale_min, self.listing_sale_max]):
            sales_dict = set(filter(lambda x: x[1] <= self.listing_sale_max, sales_dict.items()))

        elif all([self.listing_sale_min, not self.listing_sale_max]):
            sales_dict = set(filter(lambda x: self.listing_sale_min <= x[1], sales_dict.items()))

        # 得到符合策略的sku列表
        sku_list = list(map(lambda x: x[0], sales_dict))
        # 得到过滤后的集合
        data_set = set(filter(lambda x: x[4] in sku_list, oringin_data_set))
        return data_set

    @count_time_decorator(switch=count_time_decorator_switch)
    def get_platform_sales(self, sku_list: list[str], orderSourceType, sku_sales_days):
        """
        获取销量
        :param sku_list: List[sku]
        :param orderSourceType:
        :param sku_sales_days:
        :return:
        """
        sku_list = list(set(sku_list))
        batch_list = self.batch_list(sku_list, 200)
        url = """https://api-dw.zhcxkj.com/dw/erp/salesvolume/platform/salessku"""
        sales_finally = {}
        for batch_list_one in batch_list:
            sales = {}
            if orderSourceType != "all":
                param = {
                    "input": {
                        "customerId": 1,
                        "orderSourceType": orderSourceType,
                        "skus": batch_list_one,
                        "days": sku_sales_days
                    }
                }
            else:
                param = {
                    "input": {
                        "customerId": 1,
                        "orderSourceType": None,
                        "skus": batch_list_one,
                        "days": sku_sales_days
                    }
                }
            hearders = {
                "Content-Type": "application/json",
                "Authorization": "Basic aXJvYm90Ym94OmkxcjVvOEJvdGJveA==",
            }
            res = requests.post(url=url, headers=hearders, json=param)
            if isinstance(orderSourceType, int):
                for data in res.json().get('data'):
                    if data.get('orderSourceType') == orderSourceType:
                        if data["sku"] not in sales:
                            sales[data["sku"]] = data["salesVolume"]
                        else:
                            sales[data["sku"]] += data["salesVolume"]
            else:
                for data in res.json().get('data'):
                    if data["sku"] not in sales:
                        sales[data["sku"]] = data["salesVolume"]
                    else:
                        sales[data["sku"]] += data["salesVolume"]
            sales_finally.update(sales)
        return sales_finally

if __name__ == '__main__':
    ListingFilterModel(52).sku_filter(9046)